package main_gui;

import calculation.FIROptimalEquiripple;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import javax.swing.JFrame;
import my_interface.SelectType;

/**
 *
 * @author KieuOanh
 */
public class OptimalEquirippleFrame extends JFrame implements SelectType {

    FIROptimalEquiripple firo;
    public final double pi = Math.PI;
    public final double pi2 = 2 * Math.PI;

//    public OptimalEquirippleFrame() {
//        setBounds(30, 20, 900, 700);
//        setResizable(false);
//        setVisible(true);
//        setTitle("Optimal Equiripple");
//    }
    public OptimalEquirippleFrame(FIROptimalEquiripple firo) {
        this.firo = firo;
        setBounds(30, 20, 900, 700);
        setResizable(false);
        setVisible(true);
        setTitle("Optimal Equiripple");
    }

    public void setData(FIROptimalEquiripple firo) {
        this.firo = firo;
    }

    @Override
    public void paint(Graphics g) {
        boolean iError = false;
//        iError = true;
        int startX;
        if (iError) {
            startX = 510;
        } else {
            startX = 300;
        }
        g.setColor(Color.LIGHT_GRAY);
        g.fillRect(0, 0, 900, 700);
        g.setColor(Color.WHITE);
        if (iError) {
            g.fillRect(70, 100, 300, 240);
        }
        g.fillRect(70, 410, 300, 240);
        g.fillRect(startX, 100, 300, 240);
        g.fillRect(510, 410, 300, 240);

        g.setColor(Color.BLACK);
        /////////////////////////////////////////
        double d = (double) 300 / firo.M;
        double ratio_hn = 180 / (firo.hnMax - firo.hnMin);
        int point0_hn = 90 + (int) (firo.hnMax * 1.2 * ratio_hn);

        double ratio_Hw = 200 / (firo.HwMax - firo.HwMin);
        int point0_Hw = 400 + (int) (firo.HwMax * 1.2 * ratio_Hw);
        double ratioMaxMin;
        double unit;
        int index;

        g.setColor(Color.BLUE);

        //<editor-fold defaultstate="collapsed" desc="Vẽ hn(n)">
        for (int i = 1; i < firo.M; i++) {
            g.drawLine((int) (i * d) + startX, point0_hn, (int) (i * d) + startX, (int) (point0_hn - firo.hn[i] * ratio_hn));
            g.drawOval((int) (i * d) + startX - 5, (int) (point0_hn - firo.hn[i] * ratio_hn) - 5, 10, 10);
        }

        ratioMaxMin = firo.hnMax / (-firo.hnMin);
        if (ratioMaxMin > 2) {
            unit = round2(-firo.hnMin);
            index = -1;
        } else {
            unit = round2(-firo.hnMin) / 2;
            index = -2;
        }
        while (index < ratioMaxMin + 1) {
            if (index != 0 && point0_hn - (int) (index * unit * ratio_hn) > 410) {
                g.setColor(Color.BLACK);
                g.drawString(trim2(unit * index) + "", 40, point0_hn - (int) (index * unit * ratio_hn) + 5);
                g.setColor(Color.BLUE);
                g.drawLine(startX, point0_hn - (int) (index * unit * ratio_hn), startX + 3, point0_hn - (int) (index * unit * ratio_hn) + 5);
                g.drawLine(370, point0_hn - (int) (index * unit * ratio_hn), 367, point0_hn - (int) (index * unit * ratio_hn) + 5);
            }
            index++;
        }
        for (int i = 0; i < 6; i++) {
            g.drawLine(startX + i * 60, 100, startX + i * 60, 103);
            g.drawLine(startX + i * 60, 340, startX + i * 60, 337);
            g.setColor(Color.BLACK);
            g.drawString(firo.M * i / 5 + "", startX - 7 + i * 60, 355);
            g.setColor(Color.BLUE);
        }
        g.drawLine(startX, point0_hn, startX + 300, point0_hn);
        //</editor-fold>

        //<editor-fold defaultstate="collapsed" desc="Vẽ decibels">
        double ratio_dB = 215 / firo.dBMax;
        int point0_dB = 435;
        int xPrevious = 1;
        int yPrevious = (int) (ratio_dB * firo.dB[1]);

        for (int i = 2; i < 300; i++) {
            int yCurrent = (int) (ratio_dB * firo.dB[i]);
            g.drawLine(xPrevious + 510, point0_dB + yPrevious, 510 + i, point0_dB + yCurrent);
            xPrevious = i;
            yPrevious = yCurrent;
        }
        g.setColor(Color.BLACK);
        g.drawString("" + firo.wp, 503 + (int) (firo.wp * 300), 665);
        g.drawString("" + firo.ws, 503 + (int) (firo.ws * 300), 665);
        g.setColor(Color.BLUE);
        drawVertical(g, 510 + (int) (firo.wp * 300), 410);
        drawVertical(g, 510 + (int) (firo.ws * 300), 410);


        double xPr = 0;
        double yPr = firo.remez.E[0];
        for (int i = 0; i < firo.remez.E.length; i++) {
        }

        if (firo.typeSelect == BAND_PASS || firo.typeSelect == BAND_STOP) {
            g.setColor(Color.BLACK);
            g.drawString("" + firo.w2p, 503 + (int) (firo.w2p * 300), 665);
            g.drawString("" + firo.w2s, 503 + (int) (firo.w2s * 300), 665);
            g.setColor(Color.BLUE);
            drawVertical(g, 510 + (int) (firo.w2p * 300), 410);
            drawVertical(g, 510 + (int) (firo.w2s * 300), 410);
        }
        g.setColor(Color.BLACK);
        g.drawString("0", 508, 665);
        g.drawString("1", 808, 665);
        g.drawString("" + (int) firo.As, 490, 445 + (int) (firo.As * ratio_dB));
        g.drawString("" + (int) firo.dBMin, 490, 445 + (int) (firo.dBMin * ratio_dB));
        g.drawString("0", 490, 445);
        g.setColor(Color.BLUE);
        drawHorizon(g, 510, point0_dB);
        drawHorizon(g, 510, point0_dB + (int) (firo.As * ratio_dB));
        drawHorizon(g, 510, point0_dB + (int) (firo.dBMin * ratio_dB));
        //</editor-fold>

        //<editor-fold defaultstate="collapsed" desc="Ve Hw()">
        xPrevious = 0;
        yPrevious = (int) (ratio_Hw * firo.Hw[0]);
        for (int i = 1; i < 300; i++) {
            int yCurrent = (int) (ratio_Hw * firo.Hw[i]);
            g.drawLine(xPrevious + 70, point0_Hw - yPrevious, 70 + i, point0_Hw - yCurrent);
            xPrevious = i;
            yPrevious = yCurrent;
        }
        drawHorizon(g, 70, point0_Hw);
        drawHorizon(g, 70, point0_Hw - (int) ratio_Hw);
        drawVertical(g, 70 + (int) (300 * firo.ws), 410);
        drawVertical(g, 70 + (int) (300 * firo.wp), 410);

        if (firo.typeSelect == BAND_PASS || firo.typeSelect == BAND_STOP) {
            drawVertical(g, 70 + (int) (300 * firo.w2s), 410);
            drawVertical(g, 70 + (int) (300 * firo.w2p), 410);
        }


        //</editor-fold>
        g.setColor(Color.BLACK);

        //window 1
        g.drawString("Impulse Response", startX + 90, 90);
        g.drawString("h(n)", startX - 60, 220);
        g.drawString("n", startX + 90, 365);
        g.drawRect(startX, 100, 300, 240);

        for (int i = -10; i < 10; i++) {
            int yTemp = point0_hn + 5 - (int) (i * 0.1 * ratio_hn);
            if (yTemp >= 100 && yTemp <= 340) {
                g.drawString("" + ((double) i / 10), startX - 25, yTemp);
                g.drawLine(startX, point0_hn - (int) (i * 0.1 * ratio_hn), startX + 3, point0_hn - (int) (i * 0.1 * ratio_hn));
            }
        }

        //window 3
        g.drawString("Amplitude Response", 150, 405);
        g.drawString("|H(w)|", 10, 535);
        g.drawString("frequence in pi units", 170, 685);
        g.drawRect(70, 410, 300, 240);
        g.drawString("0", 60, point0_Hw + 5);
        g.drawString("1", 60, point0_Hw - (int) ratio_Hw + 5);
        g.drawString("0", 67, 665);
        g.drawString("1", 367, 665);
        g.drawString("" + firo.ws, 63 + (int) (300 * firo.ws), 665);
        g.drawString("" + firo.wp, 63 + (int) (300 * firo.wp), 665);
        g.drawString("" + firo.w2s, 63 + (int) (300 * firo.w2s), 665);
        g.drawString("" + firo.w2p, 63 + (int) (300 * firo.w2p), 665);

        //window 4
        g.drawString("Magnitude Response in dB", 600, 405);
        g.drawString("Decibels", 430, 550);
        g.drawString("frequence in pi units", 600, 685);
        g.drawRect(510, 410, 300, 240);



        ////////////////////////////////////////
        g.setFont(new Font("Courier New", Font.BOLD, 20));
        g.drawString("FIR: OPTIMAL EQUIRIPPLE DESIGN TECHNIQUE", 220, 60);
    }

    double trim2(double x) {
        return (int) (x * 100) / (double) 100;
    }

    double round2(double x) {
        return (int) (x * 100 + 0.5) / (double) 100;
    }

    void drawHorizon(Graphics g, int startX, int y) {
        for (int i = 0; i < 60; i++) {
            g.drawLine(startX + i * 5, y, startX + 1 + i * 5, y);
        }
    }

    void drawVertical(Graphics g, int x, int startY) {
        for (int i = 0; i < 48; i++) {
            g.drawLine(x, startY + i * 5, x, startY + 1 + i * 5);
        }
    }
}
